﻿define("ow-epi-imageBrowser/ImageBrowserViewModel", [
// dojo
"dojo/_base/array",
"dojo/_base/Deferred",
"dojo/dom-attr",

// dijit
"dijit/form/ToggleButton",


"ow-epi-imageBrowser/knockout-2.2.1",
"epi/shell/widget/SearchBox"
],
    function (array, Deferred, domAttr, ToggleButton, ko) {

        var getJSON = function (url, content) {
            var deferred = new Deferred();

            dojo.xhrGet({
                url: url,
                handleAs: "json",
                content: content,
                error: function (result) {
                    deferred.reject(result);
                },
                load: function (result) {
                    deferred.resolve(result);
                }
            });

            return deferred;
        };

        var postJSON = function (url, content) {
            var deferred = new Deferred();

            dojo.xhrPost({
                url: url,
                handleAs: "json",
                content: content,
                error: function (result) {
                    deferred.reject(result);
                },
                load: function (result) {
                    deferred.resolve(result);
                }
            });

            return deferred;
        };

        //
        // knockut binding for DOJO toolkit
        //
        ko.bindingHandlers.dijitValue = {
            init: function (element, valueAccessor) {
                //initialize component
                var _options = valueAccessor();

                var defaultOptions = {
                    useStandarWidget: true,
                    eventName: 'onChange',
                    getValueFunction: function (w) {
                        return w.value;
                    },
                    css: '',
                    settings: {}
                };

                var options = dojo.mixin({}, defaultOptions, _options);

                var widget;
                if (options.useStandarWidget) {
                    widget = new dijit.form[options.widget](options.settings);
                } else if (options.widget == 'epi.shell.widget.SearchBox') {
                    widget = new epi.shell.widget.SearchBox(options.settings);
                }

                widget = widget.placeAt(element);

                if (options.css) {
                    dojo.addClass(widget.domNode, options.css);
                }

                //respond to change event of the control
                dojo.connect(widget, options.eventName, function () {
                    var value = options.value;
                    if (ko.isWriteableObservable(value)) {
                        value(options.getValueFunction(widget));
                    }
                });
            },
            //respond to updates to the observable
            update: function (element, valueAccessor) {
                var options = valueAccessor();
                var widget = dijit.byNode(element.children[0]);
                if (widget) {
                    //widget.set("value", ko.utils.unwrapObservable(options.value));
                    widget.set("value", null);
                }
            }
        };

        //
        // image fade src binding
        //
        ko.bindingHandlers.fadeSrc = {
            init: function(element, valueAccessor) {
                // Initially set the element to be instantly visible/hidden depending on the value
                var value = valueAccessor();
                var imgSrc = ko.utils.unwrapObservable(value);
                if ( imgSrc) {
                    domAttr.set(element, { src: imgSrc });
                }
            },
            update: function(element, valueAccessor) {
                // Whenever the value subsequently changes, slowly fade the element in or out
                var value = valueAccessor();
                
                var imgSrc = ko.utils.unwrapObservable(value);
                if (imgSrc) {
                    domAttr.set(element, { src: imgSrc });
                    dojo.style(element, "opacity", "0.5");
                    var fadeArgs = {
                        node: element,
                        duration: 1000,
                    };
                    dojo.fadeIn(fadeArgs).play();
                }
            }
        };


        var NewDirectoryViewModel = function (imageBrowserViewModel, fileControllerUrl) {
            var self = this;

            this.isInNewDirectoryMode = ko.observable(false);
            this.directoryName = ko.observable();

            this.addDirectory = function (newDirectoryViewModel, sender) {
                self.directoryName('');
                self.isInNewDirectoryMode(true);

                dojo.query(".explorer .directory .new-directory input", dojo.query(sender).parent().parent()[0])[0].focus();
            };

            this.onNewDirectoyAction = function onNewDirectoyActionF(directory, event) {
                var keyCode = (event.which ? event.which : event.keyCode);
                if (keyCode === 13) {
                    self.onSave();
                    return false;
                }

                if (keyCode === 27) {
                    self.onCancel();
                    return false;
                }

                return true;
            };

            this.onSave = function () {
                var parameters = {
                    path: imageBrowserViewModel.directoryPath(),
                    directoryName: self.directoryName()
                };
                postJSON(fileControllerUrl + "/CreateNewDirectory", parameters).then(function (result) {
                    if (result.result) {
                        imageBrowserViewModel.mapItems(result.items);
                        self.directoryName('');
                    } else {
                        alert('Cannot add directory');
                    }
                });

                self.isInNewDirectoryMode(false);
            };

            this.onCancel = function () {
                self.isInNewDirectoryMode(false);
            };
        };

        var DirectorylViewModel = function (imageBrowserViewModel, fileControllerUrl, thumbnails) {
            var self = this;

            this.name = ko.observable();
            this.path = ko.observable();
            this.thumbnails = ko.observable(thumbnails);
            this.newName = ko.observable();
            this.countImages = ko.observable();

            this.currentThumnailIndex = ko.observable(0);
            this.currentThumbnailSrc = ko.computed(function () {
                if (thumbnails.length > 0) {
                    return thumbnails[self.currentThumnailIndex()];
                }
                return null;
            });

            this.setNextImage = function () {
                if (thumbnails.length < 2) {
                    return;
                }
                
                if (self.currentThumnailIndex() < thumbnails.length - 1) {
                    self.currentThumnailIndex(self.currentThumnailIndex() + 1);
                }
                else {
                    self.currentThumnailIndex(0);
                }
            };

            this.isEditingName = ko.observable(false);

            this.editName = function (directoryViewModel, sender) {
                self.newName(self.name());
                self.isEditingName(true);

                //dojo.query(".new-directory input", dojo.query(sender.srcElement).parent().parent()[0])[0].focus();
            };

            this.onNewNameAction = function onNewNameActionF(directory, event) {
                var keyCode = (event.which ? event.which : event.keyCode);
                if (keyCode === 13) {
                    self.saveName();
                    return false;
                }

                if (keyCode === 27) {
                    self.cancelEdit();
                    return false;
                }

                return true;
            };

            this.cancelEdit = function () {
                self.newName(self.name());
                self.isEditingName(false);
            };

            this.saveName = function () {
                var parameters = {
                    path: imageBrowserViewModel.directoryPath(),
                    name: self.name(),
                    newName: self.newName()
                };
                postJSON(fileControllerUrl + "/SaveDirectoryName", parameters).then(function (result) {
                    self.path(result.path);
                    self.name(self.newName());
                    self.isEditingName(false);
                });
            };

        };

        var ImageFileViewModel = function (imageBrowserViewModel, fileControllerUrl) {
            var self = this;

            this.name = ko.observable();
            this.path = ko.observable();
            this.thumbnailPath = ko.observable();
            this.extension = ko.observable();
            this.size = ko.observable();
            this.displayName = ko.observable();

            this.tooltip = ko.computed(function () {
                var sb = [];
                sb.push(self.displayName());
                sb.push('\r\n');
                sb.push('Image type: ' + self.extension());
                sb.push('\r\n');
                sb.push('Size: ' + self.size());

                return sb.join('');
            });

            this.showMenu = function(imageFile, evt) {
                var widget = imageBrowserViewModel.getVirtualPathProvidersViewModel().imageBrowserWidget;
                imageBrowserViewModel.getVirtualPathProvidersViewModel().onMenuClick(widget, imageFile,evt);
            };

            this.preview = function() {
                window.open(self.path());
            };

            this.edit = function () {
                var width = 800;
                var height = 600;
                var imageEditorUrl = EPi.ResolveUrlFromUI("Edit/ImageEditor/ImageEditor.aspx");
                EPi.CreateDialog(imageEditorUrl + '?openedfromfilemanager=true&parent=102', imageBrowserViewModel.refreshList, null, { src: self.path() }, { width: width, height: height });
            };

            this.deleteFile = function() {
                if (confirm('Are you sure you want to delete this file?')) {
                    var parameters = {
                        filename: self.path()
                    };
                    postJSON(fileControllerUrl + "/DeleteFile", parameters).then(function(result) {
                        if (result.result) {
                            imageBrowserViewModel.imageFiles.remove(self);
                        }
                    });
                }
            };

            this.renameFile = function() {
                var newName = prompt('Select new file name', self.displayName());
                if (newName) {
                    var parameters = {
                        filename: self.path(),
                        newName: newName
                    };
                    postJSON(fileControllerUrl + "/RenameFile", parameters).then(function(result) {
                        if (result.result) {
                            imageBrowserViewModel.refreshList();
                        }
                    });
                }
            };
        };

        var ImageSelectionViewModel = function (imageFiles, allowSelectItems) {
            var self = this;

            this.selectedImage = ko.observable();

            this.selectImage = function selectImageF(imageFile) {
                if (allowSelectItems) {
                    self.selectedImage(imageFile);
                }
                return true;
            };

            this.isFileImageSelected = function isFileImageSelectedF(imageFile) {
                return allowSelectItems && self.selectedImage() === imageFile;
            };

            this.clearSelection = function clearSelectionF() {
                self.selectedImage(null);
            };

            this.selectByName = function (imageFileName) {
                var file = imageFiles.findByName(imageFileName);
                if (file) {
                    self.selectImage(file);
                }

            };
        };

        //
        // List of directories and files for specified path
        //
        var ImageBrowserViewModel = function (virtualPathProvidersViewModel, fileControllerUrl, allowSelectItems) {
            var self = this;

            this.imageBrowserWidget = null;

            this.directoryName = ko.observable();
            this.directoryPath = ko.observable();

            this.directories = ko.observableArray();
            this.imageFiles = ko.observableArray();

            this.searchTerm = ko.observable('').extend({ throttle: 500 });
            this.searchRecursive = ko.observable(false).extend({ throttle: 500 });

            this.imageSelection = new ImageSelectionViewModel(self.imageFiles, allowSelectItems);

            this.newDirectoryViewModel = new NewDirectoryViewModel(self, fileControllerUrl);

            this.currentContextId = ko.observable();

            this.touchDirectory = ko.observable(false);

            this.deleteDirectory = function (directoryViewModel, evt) {
                if (confirm('Are you sure you want to delete this folder?')) {
                    var parameters = {
                        name: directoryViewModel.name(),
                        path: self.directoryPath()
                    };
                    postJSON(fileControllerUrl + "/DeleteDirectory", parameters).then(function (result) {
                        if (result.result) {
                            self.directories.remove(directoryViewModel);
                        }
                    });
                }
            };

            this.getVirtualPathProvidersViewModel = function() {
                return virtualPathProvidersViewModel;
            };

            this.parentPaths = ko.computed(function () {
                var directoryPath = self.directoryPath();
                if (!directoryPath) {
                    return [];
                }

                var result = [];
                var currentPath = '';
                var paths = directoryPath.split('/');

                paths = array.filter(paths, function (p) {
                    return dojo.trim(p);
                });

                for (var i = 0; i < paths.length - 1; i++) {
                    var path = dojo.trim(paths[i]);

                    var item = { name: path };
                    item.path = currentPath + '/' + path;
                    currentPath = item.path;
                    result.push(item);
                }

                if (result.length > 0) {
                    result[0].path = result[0].path + '/';
                }

                return result;
            });


            this.refreshList = function () {
                return self.reloadDirectory(self.currentContextId(), self.directoryPath());
            };

            this.reloadDirectory = function (contextId, path) {
                var parameters = {
                    contextId: contextId,
                    path: path,
                    searchTerm: self.searchTerm(),
                    searchRecursive: self.searchRecursive()
                };

                return getJSON(fileControllerUrl + "/GetImages", parameters).then(function (result) {
                    self.mapItems(result);
                });
            };

            self.searchTerm.subscribe(function () {
                self.refreshList();
            });

            self.searchRecursive.subscribe(function () {
                self.refreshList();
            });

            this.goToPath = function goToPathF(path) {
                if (self.newDirectoryViewModel.isInNewDirectoryMode()) {
                    return;
                }

                self.reloadDirectory(self.currentContextId(), path);
            };

            this.goToDirectory = function goToDirectoryF(item) {
                if (item.isEditingName()) {
                    return;
                }

                self.goToPath(item.path());
            };

            this.sortByName = function sortByNameF() {
                self.imageFiles.sort(function (left, right) {
                    return left.name() == right.name() ? 0 : (left.name() < right.name() ? -1 : 1);
                });
            };

            this.mapItems = function mapItemsF(items) {
                if (!items) {
                    self.directoryName(null);
                    self.directoryPath(null);
                    self.directories([]);
                    self.imageFiles([]);
                    return;
                }
                self.directoryName(items.DirectoryName);
                self.directoryPath(items.DirectoryPath);

                var directories = [];
                for (var i = 0; i < items.Directories.length; i++) {
                    var directory = items.Directories[i];
                    var directoryViewModel = new DirectorylViewModel(self, fileControllerUrl, directory.Thumbnails);
                    directoryViewModel.name(directory.Name);
                    directoryViewModel.countImages(directory.CountImages);
                    directoryViewModel.path(directory.Path);
                    directories.push(directoryViewModel);
                }
                self.directories(directories);

                var imageFiles = [];
                for (var j = 0; j < items.ImageFiles.length; j++) {
                    var imageFile = items.ImageFiles[j];
                    var imageFileViewModel = new ImageFileViewModel(self, fileControllerUrl);
                    imageFileViewModel.name(imageFile.Name);
                    imageFileViewModel.path(imageFile.Path);
                    imageFileViewModel.thumbnailPath(imageFile.ThumbnailPath);
                    imageFileViewModel.size(imageFile.Size);
                    imageFileViewModel.extension(imageFile.Extension);
                    imageFileViewModel.displayName(imageFile.DisplayName);
                    imageFiles.push(imageFileViewModel);
                }
                self.imageSelection.clearSelection();
                self.imageFiles(imageFiles);
                self.sortByName();
            };

            var rotateImages = function () {
                var directories = self.directories();
                for (var i = 0; i < directories.length; i++) {
                    directories[i].setNextImage();
                }

                setTimeout(rotateImages, 3000);
            };

            var init = function initF() {
                self.imageFiles.findByName = function (imageFileName) {
                    if (!imageFileName) {
                        return null;
                    }
                    return ko.utils.arrayFirst(this(), function (item) {
                        return item.name().toUpperCase() == imageFileName.toUpperCase();
                    });
                };

                rotateImages();
            };

            init();
        };


        //
        //  List of EPiServer VPP
        //
        var VirtualPathProvidersViewModel = function (fileControllerUrl, vppListing, currentContextId, allowSelectItems, reloadVppAtStart) {
            var self = this;

            this.currentVppName = ko.observable();

            var pageFilesVPP = '';

            this.isCurrentVpp = function (data) {
                return self.currentVppName() == data.name;
            };

            this.virtualPathProviders = ko.observableArray();

            this.currentVpp = new ImageBrowserViewModel(self, fileControllerUrl, allowSelectItems);

            var getCurrentVPP = function getCurrentVppF() {
                return ko.utils.arrayFirst(self.virtualPathProviders(), function (item) {
                    return item.name.toUpperCase() == self.currentVppName().toUpperCase();
                });
            };
            
            this.changeContext = function changeContextF(newContextId) {
                currentContextId = newContextId;
                self.refreshPageFilesVppPath().then(function () {
                    if (!self.currentVpp) {
                        return;
                    }

                    var current = getCurrentVPP(); // for page files we have to reload directory content
                    if (current.isPageFiles) {
                        if (current.path) {
                            self.changeVirtualPathProvider(current);
                        } else {
                            self.changeVirtualPathProvider(self.virtualPathProviders()[0]); //page files not exists -> set first available VPP
                        }
                    }
                });
            };

            this.changeVirtualPathProvider = function changeVirtualPathProviderF(vpp, e, path) {
                path = path || vpp.path;
                if (vpp.isPageFiles && !pageFilesVPP.path) {
                    if (confirm('A folder for this page has not been created, do you wish to create one now?')) {
                        postJSON(fileControllerUrl + "/EnsurePageFilesDirectory", { contextId: currentContextId }).then(function (result) {
                            pageFilesVPP.path = result.path;
                            self.changeVirtualPathProvider(vpp, e, path);
                        });
                    }
                } else {
                    self.currentVppName(vpp.name);
                    return self.currentVpp.reloadDirectory(currentContextId, path);
                }
            };

            this.createNewDirectoryInCurrentVpp = function createNewDirectoryInCurrentVppF() {
                if (!self.currentVpp.newDirectoryViewModel.isInNewDirectoryMode()) {
                    self.currentVpp.newDirectoryViewModel.addDirectory();
                }
            };

            this.setVppByPath = function setVppByPathF(fileName) {
                if (!fileName) {
                     self.changeVirtualPathProvider(self.virtualPathProviders()[0]);
                    return;
                }

                var onVppLoad = function onVppLoadF(result) {
                    if (result.result) {
                        var selectedVpp = dojo.filter(self.virtualPathProviders(), function (item) {
                            return item.name == result.vppName;
                        });
                        if (selectedVpp.length) {
                            selectedVpp = selectedVpp[0];
                            var deferred = self.changeVirtualPathProvider(selectedVpp, null, result.path);
                            Deferred.when(deferred, function () {
                                self.currentVpp.imageSelection.selectByName(result.name);
                            });
                        }

                    } else if (self.virtualPathProviders().length) {
                        self.changeVirtualPathProvider(self.virtualPathProviders()[0]);
                    }
                };

                getJSON(fileControllerUrl + "/GetFileDetails", { fileName: fileName }).then(onVppLoad);
            };

            this.isInNewDirectoryMode = function isInNewDirectoryModeF() {
                return self.currentVpp.newDirectoryViewModel.isInNewDirectoryMode();
            };

            this.refreshPageFilesVppPath = function refreshPageFilesVppPathF() {
                self.currentVpp.currentContextId(currentContextId);
                return getJSON(fileControllerUrl + "/IsPageFilesVppAvailable", { contextId: currentContextId }).then(function (result) {
                    pageFilesVPP.path = result;
                });
            };

            this.onMenuClick = null;
                        
            var getPageFilesVPP = function getPageFilesVppF(vppListing) {
                return ko.utils.arrayFirst(vppListing, function (item) {
                    return item.isPageFiles;
                });
            };

            var init = function () {
                if (vppListing && vppListing.length > 0) {
                    // init vpp array
                    for (var i = 0; i < vppListing.length; i++) {
                        var vppItem = vppListing[i];
                        vppItem.name = vppItem.name;
                        vppItem.path = vppItem.path;
                        vppItem.displayName = vppItem.displayName;

                        if (vppItem.isPageFiles === undefined) {
                            vppItem.isPageFiles = false;
                        }
                    }

                    // Page Files VPP
                    var pageFilesVpp = getPageFilesVPP(vppListing);
                    if ( !pageFilesVpp) {
                        pageFilesVPP = {
                            name: 'Page files',
                            path: '',
                            displayName: 'Page files',
                            isPageFiles: true
                        };
                        vppListing.push(pageFilesVPP);
                    }
                    self.refreshPageFilesVppPath();

                    self.virtualPathProviders(vppListing);

                    if (reloadVppAtStart || reloadVppAtStart === undefined) {
                        self.changeVirtualPathProvider(vppListing[0]);
                    }
                }
            };

            init();
        };

        return VirtualPathProvidersViewModel;
    });